package net.chathu.airgw.model.handler 
{
	import flash.utils.Dictionary;
	import net.chathu.airgw.Config;
	import net.chathu.airgw.Debug;
	import net.chathu.airgw.model.SessionData;
	import net.chathu.airgw.packets.gw.clientpackets.*;
	
	/**
	 * ...
	 * @author ze
	 */
	public class IRCPacketProcessor 
	{
		
		private static var _instance:IRCPacketProcessor;
		private var packetTypes:Dictionary;
		public function IRCPacketProcessor() 
		{
			initPacketTypes();
		}
		
		public static function init():void
		{
			instance; //Will call initPacketTypes...
		}
		
		private static function get instance():IRCPacketProcessor
		{
			if (!_instance)
			{
				_instance = new IRCPacketProcessor();
			}
			
			return _instance;
		}
		
		private function initPacketTypes():void
		{
			packetTypes = new Dictionary();
			
			addPacketType("CAP", CMDCapabilities);
			addPacketType("GWACCEPTROOMINVITE", CMDGWAcceptRoomInvite);
			addPacketType("GWCLOSEPRIV", CMDGWClosePriv);
			addPacketType("GWCHATNICK", CMDGWChatNick);
			addPacketType("GWDENYROOMINVITE", CMDGWDenyRoomInvite);
			addPacketType("GWFRIENDADD", CMDGWFriendAdd);
			addPacketType("GWFRIENDDEL", CMDGWFriendDel);
			addPacketType("GWFRIENDLIST", CMDGWFriendList);
			addPacketType("GWHELP", CMDGWHelp);
			addPacketType("GWLEAVECONFROOM", CMDGWLeaveConfRoom);
			addPacketType("GWMUTE", CMDGWMute);
			addPacketType("GWMUTELIST", CMDGWMuteList);
			addPacketType("GWSETDISTURB", CMDGWSetDisturb);
			addPacketType("GWUNMUTE", CMDGWUnMute);
			addPacketType("GWUPDATECHECK", CMDGWUpdateCheck);
			addPacketType("GWUSERINFO", CMDGWUserInfo);
			addPacketType("INVITE", CMDInvite);
			addPacketType("ISON", CMDIsOn);
			addPacketType("JOIN", CMDJoin);
			addPacketType("KICK", CMDKick);
			addPacketType("LIST", CMDList);
			addPacketType("MODE", CMDMode);
			addPacketType("NICK", CMDNick);
			addPacketType("NOTICE", CMDNotice);
			addPacketType("PART", CMDPart);
			addPacketType("PASS", CMDPass);
			addPacketType("PING", CMDPing);
			addPacketType("PONG", CMDPong);
			addPacketType("PRIVMSG", CMDPrivMsg);
			addPacketType("QUIT", CMDQuit);
			addPacketType("TOPIC", CMDTopic);
			addPacketType("USER", CMDUser);
			addPacketType("USERHOST", CMDUserHost);
			addPacketType("WHO", CMDWho);
			addPacketType("WHOIS", CMDWhois);
		}
		
		private function addPacketType(command:String, packetType:Class):void
		{
			
			if (Config.DEBUG)
			{
				if (!(new packetType() is IRCReceivablePacket))
				{
					trace("Error: " + packetType + " cannot is not an IRCReceivablePacket. Command:" + command);
					throw new Error("Error: " + packetType + " is not an IRCReceivablePacket. Command:" + command);
				}
				
				if (packetTypes[command])
				{
					trace("Duplicated IRC command definition found: " + command);
				}
			}
				
			packetTypes[command] = packetType;
		}
		
		public static function handlePacket(packetData:Array, sessionData:SessionData):void
		{
			try {
				var inst:IRCPacketProcessor = instance;
				var clazz:Class = Class(instance.packetTypes[String(packetData[0]).toUpperCase()]);
				if (clazz)
				{
					var packet:IRCReceivablePacket = IRCReceivablePacket(new clazz());
					packet.sessionData = sessionData;
					packet.data = packetData;
					packet.execute();
				} else {
					Debug.echo("Unhandled IRC command: " + packetData.join(" "));
				}
			} catch (err:Error) {
				Debug.echo("Error in packet(" + packetData[0] + "): " + err.message);
			}
		}
		
		public static function get registeredCommands():Dictionary
		{
			return instance.packetTypes;
		}
		
		public static function get availableCommands():Dictionary {
			return instance.packetTypes;
		}
		
		
	}

}